package cn.qicaiwang.open.common.utils.jwt;

import cn.qicaiwang.open.common.entity.LoginUser;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT 工具类
 */
public class JwtTokenUtil implements Serializable {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_USER = "user";

    /**
     * 5天(毫秒)
     */
    private static final long EXPIRATION_TIME = 432000000;
    /**
     * JWT密码
     */
    private static final String SECRET = "secret";




    /**
     * 使用账号和密码生成token
     * @param username 账号
     * @param password 密码
     * @return 生成的token
     */
    public static String generateTokenByUsernameAndPassword(String username, String password,String id) {
        LoginUser loginUser = new LoginUser();
        loginUser.setId(id);
        loginUser.setUsername(username);
        loginUser.setPassword(password);
        return generateToken(loginUser);
    }


    /**
     * 签发JWT
     */
    public static String generateToken(UserDetails userDetails) {
        LoginUser loginUser = (LoginUser) userDetails;
        Map<String, Object> claims = new HashMap<>(16);
        claims.put(CLAIM_KEY_USERNAME, loginUser.getUsername());
        claims.put(CLAIM_KEY_USER, loginUser);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(new Date(Instant.now().toEpochMilli() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    /**
     * 验证JWT
     */
    public static Boolean validateToken(String token, UserDetails userDetails) {
       try {
           return isTokenExpired(token);
       }catch (Exception ignore) {
           return false;
       }
    }

    /**
     * 获取token是否过期
     */
    public static Boolean isTokenExpired(String token) {
        Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    /**
     * 根据token获取user
     */
    public static LoginUser getLoginUserFromToken(String token) {
        Claims claimsFromToken = getClaimsFromToken(token);
        LoginUser loginUser = JSON.parseObject(JSON.toJSONString(claimsFromToken.get(CLAIM_KEY_USER)), LoginUser.class);
        return loginUser;
    }

    /**
     * 获取token的过期时间
     */
    public static Date getExpirationDateFromToken(String token) {
        Date expiration = getClaimsFromToken(token).getExpiration();
        return expiration;
    }

    /**
     * 解析JWT
     */
    private static Claims getClaimsFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
        return claims;
    }
}